package com.slightech.marvin.api.doc.model;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.slightech.marvin.api.doc.annotation.*;
import com.slightech.marvin.api.doc.parser.FieldCollection;
import com.slightech.marvin.api.doc.parser.IFieldParser;
import com.slightech.marvin.api.doc.util.JsonTool;
import lombok.Getter;
import lombok.Setter;
import lombok.val;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author willardwang
 * @description
 * @date 2019/07/29
 */
@Getter
@Setter
public class ApiResponse {
    private String responseExampleJson;
    private List<ApiField> responseParamList;
    private List<ApiError> errorList;

    private ApiResponse() {

    }

    public static class Builder {
        private Method method;
        private IFieldParser fieldParser;

        public ApiResponse.Builder setMethod(Method method) {
            this.method = method;
            return this;
        }

        public ApiResponse.Builder setFieldParser(IFieldParser fieldParser) {
            this.fieldParser = fieldParser;
            return this;
        }

        public ApiResponse build() {
            if (this.fieldParser == null) {
                throw new RuntimeException("fieldParse is null");
            }
            if (method == null) {
                throw new RuntimeException("method is null");
            }
            val apiResponse = new ApiResponse();
            val marvinResponse = method.getAnnotation(MarvinApiResponseParam.class);
            List<ApiField> responseParamList = new ArrayList<>();
            Map<String, Object> fieldMap = new HashMap<>();
            FieldCollection fieldCollection = null;
            if (marvinResponse != null) {
                MarvinApiResponseClass marvinApiResponseClass = marvinResponse.responseClass();
                Class responseClazz = marvinApiResponseClass.clazz();
                if (!responseClazz.getName().equals(java.lang.Void.class.getName())) {
                    MarvinApiGenericField[] marvinApiGenericFields = marvinApiResponseClass.genericField();
                    fieldCollection = this.fieldParser.parseClazzField(marvinApiResponseClass.clazz(), marvinApiGenericFields);
                } else {
                    MarvinApiParamField[] marvinApiParamFields = marvinResponse.field();
                    fieldCollection = this.fieldParser.parseMarvinApiParamField(marvinApiParamFields);
                }

                MarvinApiParamError[] marvinApiParamErrors = marvinResponse.error();
                val errorList = new ArrayList<ApiError>();
                for (MarvinApiParamError marvinApiParamError : marvinApiParamErrors) {
                    val error = new ApiError();
                    error.setCode(marvinApiParamError.code());
                    error.setMsg(marvinApiParamError.msg());
                    error.setDescription(marvinApiParamError.description());
                    errorList.add(error);
                }
                apiResponse.setErrorList(errorList);
            }

            if (fieldCollection != null) {
                responseParamList = fieldCollection.getApiFieldList();
                fieldMap = fieldCollection.getApiFieldMap();
            }
            val bootResponseMap = new HashMap<String, Object>();
            bootResponseMap.put("result", fieldMap);
            bootResponseMap.put("return_code", "SUCCESS");
            bootResponseMap.put("error_msg", "");
            bootResponseMap.put("sub_code", "SUCCESS");
            bootResponseMap.put("sub_msg", "");
            try {
                apiResponse.setResponseExampleJson(JsonTool.bean2JsonStr(bootResponseMap));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            apiResponse.setResponseParamList(responseParamList);
            return apiResponse;
        }
    }
}
